﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Microsoft.Phone.Controls;
using Microsoft.Devices;
using System.Threading;
using Microsoft.FaceSdk.Tracker;
using System.Diagnostics;
using System.Windows.Media.Imaging;
using Microsoft.FaceSdk.Common;
using Microsoft.FaceSdk.Alignment;
using Microsoft.FaceSdk.Common.Extension;

namespace TrollFacing
{
    public partial class LiveFacePage : PhoneApplicationPage
    {
        private PhotoCamera _camera;
        private readonly MOTFaceTracker _faceTracker;
        private Thread _faceDetectionThread;

        private static ManualResetEvent _pauseFramesEvent = new ManualResetEvent(true);
        private static bool _trollify = true;

        /// <summary>
        /// Constructeur
        /// </summary>
        public LiveFacePage()
        {
            InitializeComponent();

            // Initialisation du tracker
            _faceTracker = new MOTFaceTracker();

            // Initialisation de la liste des images
            var images = new List<string>();
            for (int i = 1; i < 9; i++)
            {
                images.Add(string.Format("Resources/Images/trollface_{0:00}.png", i));
            }

            TrollFacesListBox.ItemsSource = images;
            TrollFacesListBox.SelectionChanged += TrollFacesListBox_SelectionChanged;
        }

        void TrollFacesListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if (TrollFacesListBox.SelectedItem != null)
            {
                FaceDetectedImage.Source = new BitmapImage(new Uri(TrollFacesListBox.SelectedItem.ToString(), UriKind.RelativeOrAbsolute));
            }
        }

        protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
        {
            // Rien ne sert de jouer sans caméra ...
            if ((PhotoCamera.IsCameraTypeSupported(CameraType.Primary) == true) ||
                (PhotoCamera.IsCameraTypeSupported(CameraType.FrontFacing) == true))
            {
                _camera = new PhotoCamera();
                _camera.Initialized += camera_Initialized;

                CameraViewBrush.SetSource(_camera);

                CorrectCameraViewOrientation();
                OrientationChanged += (s, arg) => CorrectCameraViewOrientation();
            }
        }

        private void CorrectCameraViewOrientation()
        {
            if (this.Orientation == PageOrientation.LandscapeLeft)
                CameraViewBrushTransform.Rotation = _camera.Orientation - 90.0;
            else if (this.Orientation == PageOrientation.LandscapeRight)
                CameraViewBrushTransform.Rotation = _camera.Orientation + 90.0;
        }
        
        void camera_Initialized(object sender, CameraOperationCompletedEventArgs e)
        {
            if (e.Succeeded)
            {
                InitializeTracking();
            }
        }

        private void InitializeTracking()
        {
            _trollify = true;

            // Thread de détection du visage
            _faceDetectionThread = new System.Threading.Thread(TrackFaces);

            _faceDetectionThread.Start();
        }

        private void TrackFaces()
        {
            // Conversion en niveaux de gris pour gagner en temps de traitement
            var input = new Microsoft.FaceSdk.Image.ImageGray((int)_camera.PreviewResolution.Width, (int)_camera.PreviewResolution.Height);

            while (_trollify)
            {
                _pauseFramesEvent.WaitOne();

                _camera.GetPreviewBufferY(input.Buffer);

                Stopwatch sw = Stopwatch.StartNew();
                var faceRectangle = _faceTracker.Track(input);
                sw.Stop();

                _pauseFramesEvent.Reset();

                Deployment.Current.Dispatcher.BeginInvoke(delegate()
                {
                    DebugTextBlock.Text = string.Format("visage détecté : {0} ms, {1}", sw.ElapsedMilliseconds, !faceRectangle.IsEmpty ? "OUI" : "NON");

                    if (TrollFacesListBox.SelectedItem != null)
                    {
                        FaceDetectedImage.Margin = new Thickness(faceRectangle.Left - faceRectangle.Width / 2, faceRectangle.Top - faceRectangle.Height / 2, 0, 0);
                        FaceDetectedImage.Width = faceRectangle.Width * 2;
                        FaceDetectedImage.Height = faceRectangle.Height * 2;

                        FaceDetectedRectangle.Visibility = System.Windows.Visibility.Collapsed;
                        FaceDetectedImage.Visibility = System.Windows.Visibility.Visible;
                    }
                    else
                    {
                        FaceDetectedRectangle.Margin = new Thickness(faceRectangle.Left, faceRectangle.Top, 0, 0);
                        FaceDetectedRectangle.Width = faceRectangle.Width;
                        FaceDetectedRectangle.Height = faceRectangle.Height;

                        FaceDetectedImage.Visibility = System.Windows.Visibility.Collapsed;
                        FaceDetectedRectangle.Visibility = System.Windows.Visibility.Visible;
                    }

                    _pauseFramesEvent.Set();
                });
            }
        }
        
        protected override void OnNavigatingFrom(System.Windows.Navigation.NavigatingCancelEventArgs e)
        {
            // Nettoyage ...
            _trollify = false;

            if (_camera != null)
            {
                _camera.Initialized -= camera_Initialized;

                _camera.Dispose();
            }
        }

    }
}